//== SAGITTARIUS ============================================================================

//== BEGINNING OF CODE ===============================================================

#ifndef __SAGUTTARUIS__REAST__H_
#define __SAGUTTARUIS__REAST__H_

//== INCLUDES ========================================================================

#include "sagittarius/core/SagittariusCore.h"
#include "sagittarius/re/reCS.h"

#ifdef __cplusplus
extern "C" {
#endif

//-- AST Datatypes --

typedef enum {
    AST_NODE_TYPE_PRIMITIVE,
    //AST_NODE_TYPE_BINOP,
    AST_NODE_TYPE_CONCAT,
    AST_NODE_TYPE_UNION,//AST_NODE_TYPE_ALTERNATIVE
    AST_NODE_TYPE_INTERSECTION
} REAST_NodeType;

//expression AST node
typedef struct EXPNODE {
    REAST_NodeType type;
    //For primitive types:
    //-When node is a single sumbol, l1 = l2 = the symbol
    //-When node is a character class, l1 = start, 
    //l2 = end, inv indicates if the class is inverted or not
    //UnicodeCChar    l1; //label
    //UnicodeCChar    l2;
    RE_CharSet* cs;
    struct EXPNODE* n1;
    struct EXPNODE* n2;
    
    //special properties
    int inv; //true if node is negated
    int closed; //true if Kleene Closure applies to this node
    //int empty; //matches nothing - now represented by letting l1 = l2 = CONST_RE_NULL
    int nullable; //a function of a regular exp
} expNode;

/**
 * @fn expNode* re_createNode()
 * @brief Creates and initializes a node for use in the AST */
expNode* re_createNode();

/**
 * @fn expNode* re_destroyNode(expNode* n)
 * @brief Destroys the node and all children 
 * @param n The node to be destroyed 
 * 
 * Call this function on the root node of a tree to free memory
 * for the entire tree */
expNode* re_destroyNode(expNode* n);

/**
 * @fn expNode* re_deepCopy(expNode* n)
 * @brief Creates a copy of the tree downstream from this node */
expNode* re_deepCopy(expNode* n);

/**
 * @fn expNode* re_constructNodeUnion(expNode* r, expNode* s)
 * @returns A new union node with r and s as operands */
expNode* re_constructNodeUnionN(expNode* r, expNode* s);

/**
 * @fn expNode* re_constructNodeConcat(expNode* r, expNode* s)
 * @returns A new concatenation node with r and s as operands */
expNode* re_constructNodeConcatN(expNode* r, expNode* s);

/**
 * @fn expNode* re_constructNodeInt(expNode* r, expNode* s)
 * @returns A new intersection node with r and s as operands */
expNode* re_constructNodeIntN(expNode* r, expNode* s);

//-- Node diagnostics --
void re_printOut(expNode* n, int n_indent);
void re_printNodeType(REAST_NodeType type);

#ifdef __cplusplus
}//extern "C"
#endif

#endif
